Skip to content

Allow merging all libcore/alloc doctests into a single binary#153072

Open
jyn514 wants to merge 6 commits intorust-lang:mainfrom
ferrocene:jyn/libcore-doctest-merge
Open

Allow merging all libcore/alloc doctests into a single binary#153072
jyn514 wants to merge 6 commits intorust-lang:mainfrom
ferrocene:jyn/libcore-doctest-merge

Conversation

@jyn514
Copy link
Member

@jyn514 jyn514 commented Feb 25, 2026

View all comments

This is only the changes needed to allow merging the tests. This doesn't actually turn doctest merging on in bootstrap. I think that might be a useful follow-up, since it makes them much faster to run, but it's not without downsides because it means we'll no longer be testing that doctests have all necessary feature() attributes.

The motivation for this change is to run the tests with -C instrument-coverage and then generate a coverage report from the output. Currently, this is very expensive because it requires parsing DWARF for each doctest binary. Merging the binaries decreases the time taken from several hours to ~30 seconds.


There are several parts to this change, most of which are independent and I'm happy to split out into other PRs.

  • Upgrade process spawning logging from debug->info so it's easier to see, including in a rustdoc built without debug symbols.
  • Core doctests now support being run with -C panic=abort. Ferrocene needs this downstream for complicated reasons; it's a one-line change so I figured it's not a big deal.
  • Downgrade errors about duplicate features from a hard error to a warning. The meaning is clear here, and doctest merging often creates duplicate features since it lifts them all to the crate root. This involves changes to the compiler but generally I expect this to be low-impact.
    • Enable this new warning, as well as several related feature lints, in rustdoc. By default rustdoc doesn't lint on anything except the lints it manually adds.
  • Rustdoc now treats allow(incomplete_features) as a crate-level attribute, just like internal_features. Without this, it's possible to get hard errors if rustdoc lifts features to the crate level but not allows.
  • Core doctests now support being built with --merge-doctests=yes. In particular, I removed a few $crate usages and explicitly marked a few doctests as standalone_crate.

@rustbot
Copy link
Collaborator

rustbot commented Feb 25, 2026

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Feb 25, 2026
@rustbot
Copy link
Collaborator

rustbot commented Feb 25, 2026

r? @jdonszelmann

rustbot has assigned @jdonszelmann.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 68 candidates
  • Random selection from 13 candidates

@rust-log-analyzer

This comment has been minimized.

@jyn514 jyn514 force-pushed the jyn/libcore-doctest-merge branch from 16227c8 to d567da2 Compare February 25, 2026 04:30
@rustbot rustbot added the T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. label Feb 25, 2026
@rust-log-analyzer

This comment has been minimized.

@bjorn3
Copy link
Member

bjorn3 commented Feb 25, 2026

Merging doctest would mean that we did no longer test that the set of features in doc tests are accurate, right? Those are visible to the user.

@rust-bors

This comment has been minimized.

@jyn514
Copy link
Member Author

jyn514 commented Feb 25, 2026

Yes. That’s why this doesn’t actually switch on merging, as mentioned in the description.

@jyn514 jyn514 force-pushed the jyn/libcore-doctest-merge branch from d567da2 to 4254825 Compare February 28, 2026 22:25
@rustbot

This comment has been minimized.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 2, 2026
@rust-bors

This comment has been minimized.

@jyn514 jyn514 force-pushed the jyn/libcore-doctest-merge branch from 4254825 to 952fe7f Compare March 9, 2026 10:39
@jyn514 jyn514 force-pushed the jyn/libcore-doctest-merge branch from 952fe7f to b2229d2 Compare March 9, 2026 11:12
@rustbot
Copy link
Collaborator

rustbot commented Mar 9, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer

This comment has been minimized.

@jyn514
Copy link
Member Author

jyn514 commented Mar 9, 2026

... CI flake probably?

##[error]The runner has received a shutdown signal. This can happen when the runner service is stopped, or a manually started runner is canceled.

@jyn514
Copy link
Member Author

jyn514 commented Mar 9, 2026

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 9, 2026
@jdonszelmann
Copy link
Contributor

@bors r+ rollup

@rust-bors
Copy link
Contributor

rust-bors bot commented Mar 9, 2026

📌 Commit b2229d2 has been approved by jdonszelmann

It is now in the queue for this repository.

@rust-bors rust-bors bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 9, 2026
@jdonszelmann
Copy link
Contributor

@bors rollup=iffy
(rustdoc tests might fail, might be hard to test locally so jyn suggested to maybe even use never)

@jdonszelmann
Copy link
Contributor

@bors r-

@rust-bors rust-bors bot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Mar 9, 2026
@jdonszelmann
Copy link
Contributor

let's just rerun PR CI quickly to make sure, r=me afterwards

@jyn514 jyn514 closed this Mar 9, 2026
@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Mar 9, 2026
@jyn514 jyn514 reopened this Mar 9, 2026
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 9, 2026
@rust-log-analyzer

This comment has been minimized.

@jyn514 jyn514 force-pushed the jyn/libcore-doctest-merge branch from b2229d2 to 1c7a992 Compare March 9, 2026 15:33
@rust-log-analyzer
Copy link
Collaborator

The job aarch64-gnu-llvm-20-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
/dev/sda15       98M  6.4M   92M   7% /boot/efi
tmpfs           1.6G   16K  1.6G   1% /run/user/1001
================================================================================

Sufficient disk space available (120898892KB >= 52428800KB). Skipping cleanup.
##[group]Run echo "[CI_PR_NUMBER=$num]"
echo "[CI_PR_NUMBER=$num]"
shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
---
set -ex

# Run a subset of tests. Used to run tests in parallel in multiple jobs.

# When this job partition is run as part of PR CI, skip tidy to allow revealing more failures. The
# dedicated `tidy` job failing won't block other PR CI jobs from completing, and so tidy failures
# shouldn't inhibit revealing other failures in PR CI jobs.
if [ "$PR_CI_JOB" == "1" ]; then
  echo "PR_CI_JOB set; skipping tidy"
  SKIP_TIDY="--skip tidy"
fi

../x.py --stage 2 test \
  ${SKIP_TIDY:+$SKIP_TIDY} \
  --skip compiler \
  --skip src
#!/bin/bash

set -ex

# Run a subset of tests. Used to run tests in parallel in multiple jobs.

# When this job partition is run as part of PR CI, skip tidy to allow revealing more failures. The
# dedicated `tidy` job failing won't block other PR CI jobs from completing, and so tidy failures
# shouldn't inhibit revealing other failures in PR CI jobs.
if [ "$PR_CI_JOB" == "1" ]; then
  echo "PR_CI_JOB set; skipping tidy"
  SKIP_TIDY="--skip tidy"
fi

../x.py --stage 2 test \
  ${SKIP_TIDY:+$SKIP_TIDY} \
  --skip tests \
  --skip coverage-map \
  --skip coverage-run \
  --skip library \
  --skip tidyselftest
---
Executing "/scripts/stage_2_test_set1.sh"
+ /scripts/stage_2_test_set1.sh
PR_CI_JOB set; skipping tidy
+ '[' 1 == 1 ']'
+ echo 'PR_CI_JOB set; skipping tidy'
+ SKIP_TIDY='--skip tidy'
+ ../x.py --stage 2 test --skip tidy --skip compiler --skip src
##[group]Building bootstrap
    Finished `dev` profile [unoptimized] target(s) in 0.04s
##[endgroup]
downloading https://static.rust-lang.org/dist/2026-03-05/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz
---
test [ui] tests/ui/abi/abi-sysv64-register-usage.rs ... ignored, ignored when the architecture is aarch64
test [ui] tests/ui/abi/abi-typo-unstable.rs#feature_enabled ... ok
test [ui] tests/ui/abi/abi-typo-unstable.rs#feature_disabled ... ok
test [ui] tests/ui/abi/anon-extern-mod.rs ... ok
test [ui] tests/ui/abi/avr-sram.rs#disable_sram ... ok
test [ui] tests/ui/abi/arm-unadjusted-intrinsic.rs#aarch64 ... ok
test [ui] tests/ui/abi/avr-sram.rs#has_sram ... ok
test [ui] tests/ui/abi/avr-sram.rs#no_sram ... ok
test [ui] tests/ui/abi/arm-unadjusted-intrinsic.rs#arm ... ok
test [ui] tests/ui/abi/bad-custom.rs ... ok
test [ui] tests/ui/abi/c-stack-as-value.rs ... ok
test [ui] tests/ui/abi/c-zst.rs#aarch64-darwin ... ok
test [ui] tests/ui/abi/c-zst.rs#powerpc-linux ... ok
---
test [ui] tests/ui/asm/aarch64/ttbr0_el2.rs ... ok
test [ui] tests/ui/asm/aarch64/type-check-2-2.rs ... ok
test [ui] tests/ui/asm/aarch64/type-check-3.rs ... ok
test [ui] tests/ui/asm/aarch64/type-f16.rs ... ok
test [ui] tests/ui/asm/aarch64v8r.rs#hf ... ok
test [ui] tests/ui/asm/aarch64v8r.rs#r82 ... ok
test [ui] tests/ui/asm/aarch64/sym.rs ... ok
test [ui] tests/ui/asm/aarch64v8r.rs#sf ... ok
test [ui] tests/ui/asm/arm-low-dreg.rs ... ok
test [ui] tests/ui/asm/binary_asm_labels.rs ... ignored, only executed when the architecture is x86_64
test [ui] tests/ui/asm/asm-with-nested-closure.rs ... ok
test [ui] tests/ui/asm/cfg-parse-error.rs ... ok
test [ui] tests/ui/asm/cfg.rs#reva ... ignored, only executed when the architecture is x86_64
---
test [ui] tests/ui/const-generics/occurs-check/unused-substs-1.rs ... ok
test [ui] tests/ui/const-generics/occurs-check/unused-substs-3.rs ... ok
test [ui] tests/ui/const-generics/occurs-check/unused-substs-4.rs ... ok
test [ui] tests/ui/const-generics/occurs-check/unused-substs-5.rs ... ok
test [ui] tests/ui/const-generics/ogca/basic-fail.rs ... ok
test [ui] tests/ui/const-generics/ogca/basic.rs ... ok
test [ui] tests/ui/const-generics/ogca/generic-param-rhs.rs ... ok
test [ui] tests/ui/const-generics/ogca/rhs-but-not-root.rs ... ok
test [ui] tests/ui/const-generics/ogca/coherence-ambiguous.rs ... ok
test [ui] tests/ui/const-generics/outer-lifetime-in-const-generic-default.rs ... ok
test [ui] tests/ui/const-generics/opaque_types.rs ... ok
test [ui] tests/ui/const-generics/opaque_types2.rs ... ok
test [ui] tests/ui/const-generics/overlapping_impls.rs ... ok
test [ui] tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs#full ... ok
---
test [ui] tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs#fat2 ... ok
test [ui] tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs#fat3 ... ok
test [ui] tests/ui/extern/issue-80074.rs ... ok
test [ui] tests/ui/extern/issue-95829.rs ... ok
test [ui] tests/ui/extern/lgamma-linkage.rs ... ok
test [ui] tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs#thin1 ... ok
test [ui] tests/ui/extern/no-mangle-associated-fn.rs ... ok
test [ui] tests/ui/extern/not-in-block.rs ... ok
test [ui] tests/ui/extern/unsized-extern-derefmove.rs ... ok
test [ui] tests/ui/feature-gates/allow-features-empty.rs ... ok
---
test [ui] tests/ui/feature-gates/feature-gate-macro-derive.rs ... ok
test [ui] tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs ... ok
test [ui] tests/ui/feature-gates/feature-gate-marker_trait_attr.rs ... ok
test [ui] tests/ui/feature-gates/feature-gate-may-dangle.rs ... ok
test [ui] tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs ... ok
test [ui] tests/ui/feature-gates/feature-gate-min-generic-const-args.rs ... ok
test [ui] tests/ui/feature-gates/feature-gate-movrs_target_feature.rs ... ignored, only executed when the architecture is x86_64
test [ui] tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs ... ok
test [ui] tests/ui/feature-gates/feature-gate-min_const_fn.rs ... ok
test [ui] tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.rs ... ignored, only executed when the architecture is x86_64
---
test [ui] tests/ui/imports/ambiguous-9.rs ... ok
test [ui] tests/ui/imports/ambiguous-import-visibility-module.rs ... ok
test [ui] tests/ui/imports/ambiguous-glob-vs-expanded-extern.rs ... ok
test [ui] tests/ui/imports/ambiguous-8.rs ... ok
test [ui] tests/ui/imports/ambiguous-panic-glob-vs-multiouter.rs ... ok
test [ui] tests/ui/imports/ambiguous-panic-globvsglob.rs ... ok
test [ui] tests/ui/imports/ambiguous-panic-no-implicit-prelude.rs ... ok
test [ui] tests/ui/imports/ambiguous-panic-non-prelude-core-glob.rs ... ok
test [ui] tests/ui/imports/ambiguous-panic-non-prelude-std-glob.rs ... ok
test [ui] tests/ui/imports/ambiguous-panic-pick-core.rs ... ok
test [ui] tests/ui/imports/ambiguous-panic-pick-std.rs ... ok
---
test [ui] tests/ui/layout/null-pointer-optimization-sizes.rs ... ok
test [ui] tests/ui/layout/post-mono-layout-cycle.rs ... ok
test [ui] tests/ui/layout/randomize.rs#normal ... ok
test [ui] tests/ui/layout/randomize.rs#randomize-layout ... ok
test [ui] tests/ui/layout/rigid-alias-due-to-broken-impl.rs ... ok
test [ui] tests/ui/layout/null-pointer-optimization.rs ... ok
test [ui] tests/ui/layout/size-of-val-raw-too-big.rs ... ignored, only executed when the pointer width is 32bit (Layout computation rejects this layout for different reasons on 64-bit.)
test [ui] tests/ui/layout/reprc-power-alignment.rs ... ok
test [ui] tests/ui/layout/struct.rs ... ok
test [ui] tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs ... ok
---
---- [ui] tests/ui/feature-gates/duplicate-features.rs stdout ----

error: test compilation failed although it shouldn't!
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/feature-gates/duplicate-features.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2" "--target=aarch64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/ui/feature-gates/duplicate-features" "-A" "unused" "-W" "unused_attributes" "-A" "internal_features" "-A" "unused_parens" "-A" "unused_braces" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/aarch64-unknown-linux-gnu/native/rust-test-helpers"
stdout: none
--- stderr -------------------------------
error: the feature `if_let` has already been enabled
##[error]  --> /checkout/tests/ui/feature-gates/duplicate-features.rs:9:12
   |
LL | #![feature(if_let)] //~ WARN the feature `if_let` has already been enabled
   |            ^^^^^^
   |
   = note: `#[deny(duplicate_features)]` on by default

error: the feature `rust1` has already been enabled
##[error]  --> /checkout/tests/ui/feature-gates/duplicate-features.rs:6:12
   |
LL | #![feature(rust1)] //~ WARN the feature `rust1` has already been enabled
   |            ^^^^^

error: aborting due to 2 previous errors
------------------------------------------

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants